import type { InterLineOperate, TypePreservationPicture } from "../../typing";
import { PaintBrush } from "./paintBrush";
import { BlackBoardBg } from "./blackBoardBg";

export class BlackBoard {
    public width: number = 0; // 画板背景层的宽度
    public height: number = 0; // 画板背景层的高度
    public paintBrush!: PaintBrush;
    public blackBoardBg!: BlackBoardBg;
    public historyOperate: InterLineOperate[] = [];
    public historyOperateIndex: number = 0;

    constructor(public divEl: HTMLDivElement) {
        this.initCanvas();

        this.bindEvent();
    }

    initCanvas = () => {
        const { width, height } = this.divEl.getBoundingClientRect();
        this.width = width;
        this.height = height;

        const blackBoardBgEl = document.createElement('canvas');
        blackBoardBgEl.width = width;
        blackBoardBgEl.height = height;
        this.divEl.appendChild(blackBoardBgEl)
        this.blackBoardBg = new BlackBoardBg(blackBoardBgEl);

        const paintBrushEl = document.createElement('canvas');
        paintBrushEl.width = width;
        paintBrushEl.height = height;
        this.divEl.appendChild(paintBrushEl);
        this.paintBrush = new PaintBrush(paintBrushEl);
        this.paintBrush.bindEvent();
    }

    clearCanvas = () => {
        this.blackBoardBg.clearCanvas();
        this.paintBrush.clearCanvas();
    }

    bindEvent = (isUninstall = false) => {
        if (isUninstall) {
            this.paintBrush.bindEvent(true)
        } else {
            document.addEventListener("mouseup", this.mouseup);
        }
    }

    mouseup = () => {
        this.paintBrush.el.removeEventListener("mousemove", this.paintBrush.mouseMove);
        if (this.paintBrush.currentLinePoints.length > 3) {
            const operateObject: InterLineOperate = {
                type: this.paintBrush.type,
                options: {
                    lineWidth: this.paintBrush.lineWidth,
                    lineDash: this.paintBrush.lineType,
                    strokeStyle: this.paintBrush.lineColor,
                },
                value: [...this.paintBrush.currentLinePoints]
            }
            this.historyOperate.push(operateObject);
            this.paintBrush.currentLinePoints.length = 0;
            this.historyOperateIndex++;
        }
        console.log(this.historyOperate, this.historyOperateIndex)
    }

    // 保存画板
    preservationPicture = (type: TypePreservationPicture) => {
        const canvasEl = document.createElement('canvas');
        canvasEl.width = this.width;
        canvasEl.height = this.height;
        const ctx = canvasEl.getContext("2d")!;

        const paintBrushImg = new Image();
        paintBrushImg.src = this.paintBrush.el.toDataURL()

        const blackBoardBgImg = new Image();
        blackBoardBgImg.setAttribute('crossOrigin', '*');
        blackBoardBgImg.src = this.blackBoardBg.el.toDataURL()

        paintBrushImg.onload = () => {
            ctx.drawImage(blackBoardBgImg, 0, 0, this.width, this.height)
            ctx.drawImage(paintBrushImg, 0, 0, this.width, this.height)
            switch (type) {
                case 'clipBoard':
                    canvasEl.toBlob(async (blob) => {
                        const data = [
                            new ClipboardItem({
                                [blob!.type]: blob!,
                            }),
                        ];
                        await navigator.clipboard.write(data);
                    })
                    break;
                case 'local':
                    canvasEl.toBlob((blob) => {
                        let imgSrc = window.URL.createObjectURL(blob!);
                        let aLink = document.createElement('a')
                        aLink.download = `${Math.random()}.png`
                        aLink.href = imgSrc
                        aLink.click()
                    })
                    break;
            }
        }
    }

    // 渲染
    render = () => {
        this.clearCanvas();
        if (this.historyOperateIndex === 0) return;
        if (this.historyOperate[this.historyOperateIndex - 1]?.type === 'clear') {
            const image = this.historyOperate[this.historyOperateIndex - 1].options.bgImage;
            if (image) this.blackBoardBg.setBgImage(image);
            else this.blackBoardBg.setBgColor(this.historyOperate[this.historyOperateIndex - 1].options.bgColor!)

            this.paintBrush.clearCanvas();
            return;
        }

        const currentBgObject: { type?: 'bgImage' | 'bgColor'; bgImage?: string; bgColor?: string; } = {};

        for (let i = 0; i < this.historyOperateIndex; i++) {
            const currentType = this.historyOperate[i].type;
            const currentOptions = this.historyOperate[i].options;
            const currentValue = this.historyOperate[i].value;
            switch (currentType) {
                case 'bgImage':
                case 'bgColor':
                    currentBgObject.type = currentType;
                    currentBgObject[currentType] = currentOptions[currentType];
                    break;
                case 'pen':
                case 'fluorescence':
                case 'eraser':
                    this.paintBrush.setLineStyle(currentOptions, currentType)
                    const length = currentValue.length;
                    let currentLineBeginPoint = currentValue[0];
                    for (let j = 2; j < length; j++) {
                        this.paintBrush.ctx.beginPath();
                        const lastTwoPoints = [currentValue[j - 1], currentValue[j]];
                        const controlPoint = lastTwoPoints[0];
                        const endPoint: [number, number] = [(lastTwoPoints[0][0] + lastTwoPoints[1][0]) / 2, (lastTwoPoints[0][1] + lastTwoPoints[1][1]) / 2];
                        this.paintBrush.drawLine(currentLineBeginPoint, controlPoint, endPoint)
                        currentLineBeginPoint = [...endPoint]
                    }
            }
        }
        if (currentBgObject.type === "bgImage") {
            this.blackBoardBg.setBgImage(currentBgObject.bgImage!);
        } else {
            this.blackBoardBg.setBgColor(currentBgObject.bgColor!);
        }
    }

    // 上一步
    previousStep = () => {
        if (this.historyOperateIndex == 0) {
            this.historyOperateIndex = 0;
        } else {
            this.historyOperateIndex--;
        }
        this.render()
    }
    // 下一步
    nextStep = () => {
        if (this.historyOperateIndex == this.historyOperate.length) {
            this.historyOperateIndex = this.historyOperate.length;
        } else {
            this.historyOperateIndex++;
        }
        this.render()
    }
    // 清空画布
    clear = () => {
        this.historyOperate.splice(this.historyOperateIndex);
        this.historyOperateIndex++;
        this.historyOperate.push({
            type: 'clear',
            options: {
                bgImage: this.blackBoardBg.bgImage,
            },
            value: []
        });
        this.paintBrush.clearCanvas();
    }
    // 设置画布背景
    setCanvasBg = (type: 'bgColor' | 'bgImage' = 'bgColor', bg: string) => {
        this.historyOperate.splice(this.historyOperateIndex);
        this.historyOperateIndex++;
        this.historyOperate.push({
            type: type,
            options: {
                [type]: bg,
            },
            value: []
        })
        if (type === 'bgColor') {
            this.blackBoardBg.setBgColor(bg)
        } else {
            this.blackBoardBg.setBgImage(bg)
        }
    }
}

//     drawBox = (x: number, y: number, w: number, h: number) => {
//         const smallBox = (x: number, y: number) => {
//             const radius = 5;
//             this.ctx.save();
//             this.ctx.lineWidth = 1;
//             this.ctx.beginPath();
//             this.ctx.rect(x - radius, y - radius, 2 * radius, 2 * radius);
//             this.ctx.stroke();
//             this.ctx.restore();
//         }
//         const points = [
//             [x, y], // 左上
//             [x + w / 2, y], // 上中
//             [x + w, y], // 右上
//             [x, y + h / 2], // 左中
//             [x + w, y + h / 2], // 右中
//             [x, y + h], // 左下
//             [x + w / 2, y + h], // 下中
//             [x + w, y + h], // 右下
//             [x + w / 2, y - 40], // 上上
//         ]
//         points.forEach(item => {
//             smallBox(item[0], item[1])
//         })
//     }